package gee

import (
	"net/http"
	"os"
	"path"
)

type GroupRoute struct {
	prefix      string
	middlewares []HandlerFunc
	engine      *Engine
}

func (group *GroupRoute) Group(prefix string) *GroupRoute {
	engine := group.engine
	newGroup := &GroupRoute{
		prefix: group.prefix + prefix,
		engine: engine,
	}
	engine.groups = append(engine.groups, newGroup)
	return newGroup
}

func (group *GroupRoute) USE(middlewares ...HandlerFunc) {
	group.middlewares = append(group.middlewares, middlewares...)
}

func (group *GroupRoute) addRoute(method string, comp string, handler HandlerFunc) {
	pattern := group.prefix + comp
	//log.Printf("Route %4s - %s", method, pattern)
	group.engine.router.addRoute(method, pattern, handler)
}

// GET defines the method to add GET request
func (group *GroupRoute) GET(pattern string, handler HandlerFunc) {
	group.addRoute("GET", pattern, handler)
}

// POST defines the method to add POST request
func (group *GroupRoute) POST(pattern string, handler HandlerFunc) {
	group.addRoute("POST", pattern, handler)
}

// 增加静态目录
func (group *GroupRoute) createStaticHandler(relativePath string, fs http.FileSystem) HandlerFunc {
	absolutePath := path.Join(group.prefix, relativePath)
	fileServer := http.StripPrefix(absolutePath, http.FileServer(fs))
	return func(c *Context) {
		file := c.Params["filepath"]
		// Check if file exists and/or if we have permission to access it
		if _, err := fs.Open(file); err != nil {
			c.Status(http.StatusNotFound)
			return
		}

		fileServer.ServeHTTP(c.Writer, c.Req)
	}
}

// serve static files
func (group *GroupRoute) Static(relativePath string, root string) {
	handler := group.createStaticHandler(relativePath, justFilesFilesystem{http.Dir(root), -1})
	urlPattern := path.Join(relativePath, "/*filepath")
	// Register GET handlers
	group.GET(relativePath, handler)
	group.GET(urlPattern, handler)
}

type justFilesFilesystem struct {
	fs http.FileSystem
	// readDirBatchSize - configuration parameter for `Readdir` func
	readDirBatchSize int
}

func (fs justFilesFilesystem) Open(name string) (http.File, error) {
	f, err := fs.fs.Open(name)
	if err != nil {
		return nil, err
	}
	return neuteredStatFile{File: f, readDirBatchSize: fs.readDirBatchSize}, nil
}

type neuteredStatFile struct {
	http.File
	readDirBatchSize int
}

func (e neuteredStatFile) Stat() (os.FileInfo, error) {
	s, err := e.File.Stat()
	if err != nil {
		return nil, err
	}
	if s.IsDir() {
		//	LOOP:
		//for {
		fl, err := e.File.Readdir(e.readDirBatchSize)
		// switch err {
		// case io.EOF:
		// 	break LOOP
		// case nil:
		// 	for _, f := range fl {
		// 		if f.Name() == "index.html" {
		// 			return s, err
		// 		}
		// 	}
		// default:
		// 	return nil, err
		// }
		if err != nil {
			return nil, err
		}
		for _, f := range fl {
			if f.Name() == "index.html" {
				return s, err
			}
		}
		//}
		return nil, os.ErrNotExist
	}
	return s, err
}
